/**
 * Client-side router for the chat application
 */
import {roomApi} from "./api.js"
import { ui } from "./ui.js";
import { wsManager } from "./websocket.js";

class Router {
    constructor() {
        this.routes = new Map();
        this.currentRoute = null;
        this.currentParams = {};
        
        this.setupEventListeners();
        this.setupRoutes();
    }

    /**
     * Setup event listeners for navigation
     */
    setupEventListeners() {
        // Handle browser back/forward buttons
        window.addEventListener('popstate', (event) => {
            this.handlePopState(event);
        });

        // Handle clicks on navigation links
        document.addEventListener('click', (event) => {
            const link = event.target.closest('a[href]');
            if (link && this.isInternalLink(link)) {
                event.preventDefault();
                this.navigate(link.getAttribute('href'));
            }
        });
    }

    /**
     * Setup application routes
     */
    setupRoutes() {
        this.addRoute('/', this.renderHomePage.bind(this));
        this.addRoute('/room/:roomId', this.renderRoomPage.bind(this));
        this.addRoute('/join/:inviteCode', this.renderJoinPage.bind(this));
    }

    /**
     * Add a route
     */
    addRoute(path, handler) {
        this.routes.set(path, handler);
    }

    /**
     * Navigate to a path
     */
    navigate(path, replace = false) {
        if (path === window.location.pathname) {
            return;
        }

        // Update browser history
        if (replace) {
            window.history.replaceState(null, '', path);
        } else {
            window.history.pushState(null, '', path);
        }

        // Route to the new path
        this.route(path);
    }

    /**
     * Route to a path
     */
    route(path = window.location.pathname) {
        const { route, params } = this.matchRoute(path);
        
        if (route) {
            this.currentRoute = route;
            this.currentParams = params;
            
            try {
                route.handler(params);
            } catch (error) {
                console.error('Route handler error:', error);
                this.renderErrorPage('An error occurred while loading the page.');
            }
        } else {
            this.renderNotFoundPage();
        }
    }

    /**
     * Match a path to a route
     */
    matchRoute(path) {
        for (const [pattern, handler] of this.routes) {
            const params = this.matchPattern(pattern, path);
            if (params !== null) {
                return { route: { pattern, handler }, params };
            }
        }
        return { route: null, params: {} };
    }

    /**
     * Match a path against a route pattern
     */
    matchPattern(pattern, path) {
        // Convert pattern to regex
        const paramNames = [];
        const regexPattern = pattern
            .replace(/\/:([^\/]+)/g, (match, paramName) => {
                paramNames.push(paramName);
                return '/([^/]+)';
            })
            .replace(/\//g, '\\/');

        const regex = new RegExp(`^${regexPattern}$`);
        const match = path.match(regex);

        if (match) {
            const params = {};
            for (let i = 0; i < paramNames.length; i++) {
                params[paramNames[i]] = decodeURIComponent(match[i + 1]);
            }
            return params;
        }

        return null;
    }

    /**
     * Handle browser back/forward navigation
     */
    handlePopState(event) {
        this.route();
    }

    /**
     * Check if a link is internal
     */
    isInternalLink(link) {
        const href = link.getAttribute('href');
        return href && (
            href.startsWith('/') || 
            href.startsWith('#') || 
            href.startsWith(window.location.origin)
        );
    }

    /**
     * Render home page
     */
    async renderHomePage(params) {
        this.hideAllPages();
        this.showPage('home-page');
        
        // Set page title
        document.title = 'LAN Chat Room';
        
        // Clear any existing user session when returning to home
        this.clearUserSession();
        
        // Setup form handlers
        this.setupHomePageHandlers();
    }

    /**
     * Render room page
     */
    async renderRoomPage(params) {
        const { roomId } = params;
        
        try {
            this.showLoading();
            
            // Check if user has session for this room
            const userSession = sessionStorage.get('currentUser');
            if (!userSession || userSession.roomId !== roomId) {
                console.log('No valid session found for room:', roomId);
                console.log('Current session:', userSession);
                
                // Clear invalid session data
                this.clearUserSession();
                
                // Redirect to home with error message
                this.hideLoading();
                this.showError('You need to join the room first.');
                
                setTimeout(() => {
                    this.navigate('/', true);
                }, 2000);
                return;
            }

            // Get room information
            const roomInfo = await roomApi.getInfo(roomId);
            
            this.hideLoading();
            this.hideAllPages();
            this.showPage('room-page');
            
            // Set page title
            document.title = `${roomInfo.room.name} - LAN Chat Room`;
            
            // Setup room page
            this.setupRoomPage(roomInfo.room, userSession);
            
        } catch (error) {
            this.hideLoading();
            console.error('Failed to load room:', error);
            
            if (error.status === 404) {
                this.showError('Room not found. The room may have been deleted or the ID is incorrect.');
            } else if (error.status === 403) {
                this.showError('Access denied. You do not have permission to access this room.');
            } else {
                this.showError('Failed to load room. Please try again.');
            }
            
            // Redirect to home after error
            setTimeout(() => {
                this.navigate('/', true);
            }, 3000);
        }
    }

    /**
     * Render join invite page
     */
    async renderJoinPage(params) {
        const { inviteCode } = params;
        
        try {
            this.showLoading();
            
            // Validate invite code
            const inviteInfo = await roomApi.validateInvite(inviteCode);
            
            this.hideLoading();
            this.hideAllPages();
            this.showPage('join-invite-page');
            
            // Set page title
            document.title = `Join ${inviteInfo.room.name} - LAN Chat Room`;
            
            // Setup join page
            this.setupJoinPage(inviteInfo.room, inviteCode);
            
        } catch (error) {
            this.hideLoading();
            console.error('Failed to validate invite:', error);
            this.showError('Invalid or expired invite link.');
            
            // Redirect to home after error
            setTimeout(() => {
                this.navigate('/', true);
            }, 3000);
        }
    }

    /**
     * Render 404 page
     */
    renderNotFoundPage() {
        this.hideAllPages();
        this.showError('Page not found.', 'The page you are looking for does not exist.');
    }

    /**
     * Render error page
     */
    renderErrorPage(message, details = '') {
        this.hideAllPages();
        this.showError(message, details);
    }

    /**
     * Setup home page event handlers
     */
    setupHomePageHandlers() {
        // Create room form
        const createRoomForm = document.getElementById('create-room-form');
        if (createRoomForm) {
            createRoomForm.addEventListener('submit', async (event) => {
                event.preventDefault();
                await this.handleCreateRoom(event.target);
            });
        }

        // Join room form
        const joinRoomForm = document.getElementById('join-room-form');
        if (joinRoomForm) {
            joinRoomForm.addEventListener('submit', async (event) => {
                event.preventDefault();
                await this.handleJoinRoom(event.target);
            });
        }
    }

    /**
     * Setup join page event handlers
     */
    setupJoinPage(room, inviteCode) {
        // Update room information display
        const roomNameEl = document.getElementById('invite-room-name');
        const memberCountEl = document.getElementById('invite-member-count');
        const maxUsersEl = document.getElementById('invite-max-users');
        const passwordGroupEl = document.getElementById('invite-password-group');

        if (roomNameEl) roomNameEl.textContent = room.name;
        if (memberCountEl) memberCountEl.textContent = room.memberCount;
        if (maxUsersEl) maxUsersEl.textContent = room.maxUsers;

        // Show password field if room requires password
        if (passwordGroupEl) {
            if (room.hasPassword) {
                passwordGroupEl.classList.remove('hidden');
            } else {
                passwordGroupEl.classList.add('hidden');
            }
        }

        // Setup form handler
        const joinForm = document.getElementById('invite-join-form');
        if (joinForm) {
            joinForm.addEventListener('submit', async (event) => {
                event.preventDefault();
                await this.handleInviteJoin(event.target, room.id, inviteCode);
            });
        }

        // Setup cancel button
        const cancelBtn = document.getElementById('invite-cancel');
        if (cancelBtn) {
            cancelBtn.addEventListener('click', () => {
                this.navigate('/');
            });
        }
    }

    /**
     * Setup room page
     */
    setupRoomPage(room, userSession) {
        // This will be handled by the UI manager
        // We just need to trigger the room setup
        if (ui) {
            ui.setupRoomPage(room, userSession);
        }
    }

    /**
     * Handle create room form submission
     */
    async handleCreateRoom(form) {
        try {
            const formData = new FormData(form);
            const roomData = {
                name: formData.get('roomName'),
                password: formData.get('password'),
                maxUsers: formData.get('maxUsers'),
                creatorNickname: formData.get('creatorNickname')
            };

            // Validate required fields
            if (!roomData.name || !roomData.creatorNickname) {
                throw new Error('Room name and creator nickname are required');
            }

            // Validate field lengths and formats
            if (roomData.name.trim().length === 0) {
                throw new Error('Room name cannot be empty');
            }
            
            if (roomData.creatorNickname.trim().length === 0) {
                throw new Error('Creator nickname cannot be empty');
            }

            if (roomData.name.length > 50) {
                throw new Error('Room name is too long (max 50 characters)');
            }

            if (roomData.creatorNickname.length > 30) {
                throw new Error('Nickname is too long (max 30 characters)');
            }

            this.showLoading('Creating room...');
            
            const result = await roomApi.create(roomData);
            console.log('Room created successfully:', result);
                
            this.hideLoading();
            showToast('Room created successfully!', 'success');
            
            // Navigate to room page - session is now established
            this.navigate(`/room/${result.room.id}`);
            
        } catch (error) {
            this.hideLoading();
            console.error('Failed to create room:', error);
            
            // Show more specific error messages
            let errorMessage = error.message;
            if (error.message.includes('fetch') || error.message.includes('network')) {
                errorMessage = 'Unable to connect to server. Please check your internet connection.';
            } else if (error.status === 400) {
                errorMessage = error.response?.error || error.message;
            } else if (error.status >= 500) {
                errorMessage = 'Server error occurred. Please try again later.';
            }
            
            this.showError(errorMessage);
        }
    }

    /**
     * Handle join room form submission
     */
    async handleJoinRoom(form) {
        try {
            const formData = new FormData(form);
            const roomId = formData.get('roomId');
            const userData = {
                nickname: formData.get('nickname'),
                password: formData.get('password')
            };

            this.showLoading('Joining room...');
            
            await roomApi.join(roomId, userData);
            
            this.hideLoading();
            showToast('Joined room successfully!', 'success');
            
            // Navigate to room page
            this.navigate(`/room/${roomId}`);
            
        } catch (error) {
            this.hideLoading();
            console.error('Failed to join room:', error);
            this.showError(error.message);
        }
    }

    /**
     * Handle invite join form submission
     */
    async handleInviteJoin(form, roomId, inviteCode) {
        try {
            const formData = new FormData(form);
            const userData = {
                nickname: formData.get('nickname'),
                password: formData.get('password')
            };

            this.showLoading('Joining room...');
            
            await roomApi.join(roomId, userData);
            
            this.hideLoading();
            showToast('Joined room successfully!', 'success');
            
            // Navigate to room page
            this.navigate(`/room/${roomId}`);
            
        } catch (error) {
            this.hideLoading();
            console.error('Failed to join room:', error);
            this.showError(error.message);
        }
    }

    /**
     * Utility methods for page management
     */
    hideAllPages() {
        const pages = document.querySelectorAll('.page');
        pages.forEach(page => page.classList.add('hidden'));
    }

    showPage(pageId) {
        const page = document.getElementById(pageId);
        if (page) {
            page.classList.remove('hidden');
        }
    }

    showLoading(message = 'Loading...') {
        const loadingScreen = document.getElementById('loading-screen');
        const loadingText = loadingScreen.querySelector('p');
        
        if (loadingText) {
            loadingText.textContent = message;
        }
        
        if (loadingScreen) {
            loadingScreen.classList.remove('hidden');
        }
    }

    hideLoading() {
        const loadingScreen = document.getElementById('loading-screen');
        if (loadingScreen) {
            loadingScreen.classList.add('hidden');
        }
    }

    showError(message, details = '') {
        const errorDisplay = document.getElementById('error-display');
        const errorMessage = document.getElementById('error-message');
        
        if (errorMessage) {
            errorMessage.innerHTML = `
                <strong>${sanitizeHtml(message)}</strong>
                ${details ? `<br><small>${sanitizeHtml(details)}</small>` : ''}
            `;
        }
        
        if (errorDisplay) {
            errorDisplay.classList.remove('hidden');
        }

        // Setup error close handler
        const errorCloseBtn = document.getElementById('error-close');
        if (errorCloseBtn) {
            errorCloseBtn.onclick = () => {
                errorDisplay.classList.add('hidden');
            };
        }
    }

    hideError() {
        const errorDisplay = document.getElementById('error-display');
        if (errorDisplay) {
            errorDisplay.classList.add('hidden');
        }
    }

    clearUserSession() {
        sessionStorage.remove('currentUser');
        sessionStorage.remove('currentRoom');
        
        // Disconnect WebSocket if connected
        if (wsManager.isConnected) {
            wsManager.disconnect();
        }
    }

    /**
     * Get current route information
     */
    getCurrentRoute() {
        return {
            pattern: this.currentRoute?.pattern,
            params: this.currentParams,
            path: window.location.pathname
        };
    }

    /**
     * Check if currently on a specific route
     */
    isCurrentRoute(pattern) {
        return this.currentRoute?.pattern === pattern;
    }
}

// Global router instance
const router = new Router();

// Initialize routing when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    router.route();
});

// Export for use in other modules
window.router = router;